package com.idanchuang.component.core.util;

import com.idanchuang.component.core.config.AbstractCryptConfigBean;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * 加解密工具类
 *
 * @author kamjin1996
 */
@SuppressWarnings("all")
public abstract class AbstractCryptUtil {

    private static final String CRYPT_WAY = "AES";
    private static final String ALGORITHM_MODE_COMPLEMENT = "AES/ECB/PKCS5Padding"; // 算法/模式/补码方式
    private static final String BYTE_CONTROL = "utf-8";
    private static final String SECURE_RANDOM_INSTANCE_NAME = "SHA1PRNG";

    /**
     * 加密
     *
     * @param sSrc
     * @return
     */
    protected static String doEncrypt(String sSrc, AbstractCryptConfigBean abstractCryptConfigBean) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
        if (sSrc == null || "".equals(sSrc)) {
            return sSrc;
        }
        // 如果加密过了. 则不作加密
        if (sSrc.startsWith(abstractCryptConfigBean.getPrefix())) {
             return sSrc;
        }
        KeyGenerator kgen = KeyGenerator.getInstance(CRYPT_WAY);
        SecureRandom secureRandom = SecureRandom.getInstance(SECURE_RANDOM_INSTANCE_NAME);
        secureRandom.setSeed(abstractCryptConfigBean.getSecretKey().getBytes());
        kgen.init(abstractCryptConfigBean.getAes().getStandSupport(), secureRandom);

        byte[] encodeFormat = kgen.generateKey().getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(encodeFormat, CRYPT_WAY);

        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_COMPLEMENT);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes(BYTE_CONTROL));

        // 此处使用BASE64做转码功能，能起到2次加密的作用。
        return abstractCryptConfigBean.getPrefix() + new Base64().encodeToString(encrypted);
    }

    /**
     * 解密
     *
     * @param sSrc
     * @return
     */
    protected static String doDecrypt(String sSrc, AbstractCryptConfigBean abstractCryptConfigBean) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
        if (sSrc == null || "".equals(sSrc) || sSrc.length() < 24) {
            return sSrc;
        }
        String prefix = abstractCryptConfigBean.getPrefix();
        if (sSrc.startsWith(prefix)) {
            sSrc = sSrc.substring(prefix.length());
        }
        KeyGenerator kgen = KeyGenerator.getInstance(CRYPT_WAY);
        SecureRandom secureRandom = SecureRandom.getInstance(SECURE_RANDOM_INSTANCE_NAME);
        secureRandom.setSeed(abstractCryptConfigBean.getSecretKey().getBytes());

        // kgen.init(checkOrGetDbCryptSupport(), new SecureRandom(sKey.getBytes()));
        kgen.init(abstractCryptConfigBean.getAes().getStandSupport(), secureRandom);

        SecretKeySpec secretKeySpec = new SecretKeySpec(kgen.generateKey().getEncoded(), CRYPT_WAY);
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_COMPLEMENT);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] decodeBytes = new Base64().decode(sSrc);
        // 防止对明文误解密后返回空
        if (decodeBytes == null || decodeBytes.length == 0) {
            return sSrc;
        }
        byte[] original = cipher.doFinal(decodeBytes);
        return new String(original, BYTE_CONTROL);
    }

}
